在上一片文章中Handler 消息机制源码分析(一)中我们分析了 Handler 中创建 Handler ,并且会绑定 Looper 。这篇文章中我们将分析下 Looper 的工作方式。
Handler 在创建时会绑定一个 Looper 对象,而Looper 如果用户不进行显式传入,会在 Handler 中调用 Looper.myLooper() 来创建一个 Looper 对象。
那什么是 Looper 呢? Android 中对于 Looper 类的注释中是这样描述的:“Class used to run a message loop for a thread”。大概意思是指这个类是用来为一个线程做消息循环。而 Looper 类本身被声明为 final 类型的,同时它的构造方法也被声明为 final 类型。所以我们如果要获取其中的 Looper 实例或者使用 Looper 的方法需要使用其中提供的两种静态方法:
我们可以看到,无论是 getMainLooper() 方法还是 myLooper() 方法,获取的 Looper 都是直接返回已经初始化的对象。那它们的初始化在哪操作的呢?如下图所示:
我们可以看到,主线程 Looper 和子线程 Looper 创建的区别在于一个 quitAllowed 变量(主线程为 false , 子线程为 true )。而最终这个变量会传入到 Looper 构造方法中用于构造 MessageQueue 。而 Looper 中的线程绑定的是当前线程。如下图所示:
这样的话,结合上一篇,我们可以发现,直接在子线程中使用 Handler handler = new Handler(),会调用 Looper.myLooper() 方法获取 Looper 对象,在这之前并没有调用 Looper.prepare() 方法进行初始化,所以 sThreadLocal.get() 中会返回 null ,进而报错。
那大家或许会问,主线程中的 mainLooper 是何时进行初始化的呢,为什么主线程中直接 new Handler() 不会报错呢?其实这个主线程 Handler 在应用启动时就已经进行了初始化,具体启动时机需要在后面继续分析呢~😊
*ps:后续文章传送门:*